package com.medeolinx.control;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.medeolinx.control.util.Constans;
import com.medeolinx.model.ModelManager;
import com.medeolinx.model.data.GeneData;
import com.medeolinx.model.data.Terrain;
import com.medeolinx.model.data.User;

/**
 * handle Album related URL:
 * 
 */
@Controller
public class AlbumController {
	private static class Links {
		static final String ADD_ALBUM = "/album_add";
		static final String DEL_ALBUM = "/album_del";
		static final String UPLOAD_TERRAIN = "/terrain_upload";
		static final String GET_TERRAIN = "/terrain";
		static final String DEL_TERRAIN = "/del_terrain";
	}

	private static class ViewPages {
		static String REDIRECT_LOGIN = "redirect:/index.html";
		static String HOME = "home";
		static String TERRAIN = "terrain";
	}

	@Autowired(required = true)
	private ModelManager modelManager;

	@RequestMapping(value = Links.ADD_ALBUM)
	public String addAlbum(@RequestParam("name") String name, HttpSession session, Model model) {
		User user = (User) session.getAttribute(Constans.Http.USER);
		if (user == null) {
			return ViewPages.REDIRECT_LOGIN;
		} else {
			try {
				user = modelManager.addAlbum(user, name);
				session.setAttribute(Constans.Http.USER, user);
				model.addAttribute(Constans.Http.MESSAGE, "Succeed to create new album " + name + ".");
			} catch (Throwable e) {
				model.addAttribute(Constans.Http.ERROR, "Failed to create new album " + name + ". Reason: " + e.getMessage());
			}
		}
		return ViewPages.HOME;
	}

	@RequestMapping(value = Links.DEL_ALBUM)
	public String delAlbum(@RequestParam("id") int id, HttpSession session, Model model) {
		User user = (User) session.getAttribute(Constans.Http.USER);
		if (user == null) {
			return ViewPages.REDIRECT_LOGIN;
		} else
			try {
				user = modelManager.delAlbum(user, id);
				session.setAttribute(Constans.Http.USER, user);
				model.addAttribute(Constans.Http.MESSAGE, "Succeed to remove album.");
			} catch (Throwable e) {
				model.addAttribute(Constans.Http.ERROR, "Failed to remove album" + ". Reason: " + e.getMessage());
			}

		return ViewPages.HOME;
	}

	@RequestMapping(value = Links.UPLOAD_TERRAIN, method = RequestMethod.POST)
	public String uploadTerrain(@RequestParam("album_id") int id, @RequestParam("terrain_name") String name, @RequestParam("description") String desc,
			@RequestParam("file") MultipartFile file, HttpSession session, Model model) {
		User user = (User) session.getAttribute(Constans.Http.USER);
		if (user == null) {
			return ViewPages.REDIRECT_LOGIN;

		} else if (!file.isEmpty()) {
			BufferedReader br = null;
			try {
				br = new BufferedReader(new InputStreamReader(file.getInputStream()));
				String strLine;

				Terrain tn = new Terrain();
				tn.setName(name);
				tn.setDescription(desc);

				Pattern pattern = Pattern.compile("^.*\\t*" + "\\d*[.]?\\d*\\t*" + "\\d*[.]?\\d*\\t*" + "\\d*[.]?\\d*\\t*" + "\\d*[.]?\\d*\\t*"
						+ "\\d*\\t*\\d{1}\\t*$");
				Matcher matcher = null;
				while ((strLine = br.readLine()) != null) {
					matcher = pattern.matcher(strLine);
					if (matcher.matches()) {
						String[] data = strLine.split("\\t+");
						GeneData d = new GeneData();
						d.setTerrain(tn);
						d.setName(data[0]);
						d.setHeight(Double.parseDouble(data[1]));
						d.setXWidth(Double.parseDouble(data[2]));
						d.setXPosition(Double.parseDouble(data[3]));
						d.setYWidth(Double.parseDouble(data[4]));
						d.setYPosition(Double.parseDouble(data[5]));
						d.setGeneSet(Integer.parseInt(data[6]));
						d.setVisable(Short.parseShort(data[7]));
						tn.getGeneDatas().add(d);
						d.setTerrain(tn);
					}
				}
				modelManager.addTerrain(id, tn);
				user = modelManager.getUser(user.getName(), user.getPassword());
				session.setAttribute(Constans.Http.USER, user);
				model.addAttribute(Constans.Http.MESSAGE, "succeed to add a terrain.");

			} catch (IOException e) {
				model.addAttribute(Constans.Http.ERROR, "Failed to add a terrain. Reason: " + e.getMessage());
				e.printStackTrace();
			} catch (Throwable e) {
				model.addAttribute(Constans.Http.ERROR, "Failed to add a terrain. Reason: " + e.getMessage());
				e.printStackTrace();
			} finally {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ViewPages.HOME;
	}

	@RequestMapping(value = Links.GET_TERRAIN)
	public String getTerrain(@RequestParam("id") int id, HttpSession session, Model model) {
		User user = (User) session.getAttribute(Constans.Http.USER);
		if (user == null) {
			return ViewPages.REDIRECT_LOGIN;
		} else
			try {
				Terrain tn = modelManager.getTerrain(id);
				model.addAttribute("terrain", tn);
			} catch (Throwable e) {
				model.addAttribute(Constans.Http.ERROR, "Failed to get terrain" + ". Reason: " + e.getMessage());
			}
		return ViewPages.TERRAIN;
	}

	@RequestMapping(value = Links.DEL_TERRAIN)
	public String delTerrain(@RequestParam("id") int id, HttpSession session, Model model) {
		User user = (User) session.getAttribute(Constans.Http.USER);
		if (user == null) {
			return ViewPages.REDIRECT_LOGIN;
		} else
			try {
				user = modelManager.delTerrain(user, id);
				session.setAttribute(Constans.Http.USER, user);
				model.addAttribute(Constans.Http.MESSAGE, "Succeed to remove terrain.");
			} catch (Throwable e) {
				model.addAttribute(Constans.Http.ERROR, "Failed to remove terrain" + ". Reason: " + e.getMessage());
			}
		return ViewPages.HOME;
	}
}
